package cn.blnp.net.flowable.event.bound.timer;

import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

/**
 * <h3>边界事件-定时器边界事件</h3>
 *
 * @author <a href="mailto:blnp.yibin@qq.com">lyb</a>
 * @version 1.0
 * @since 2025/5/8 15:55
 */
@Slf4j
@SpringBootTest
public class BoundTimerEvent {

    @Resource
    private RepositoryService repositoryService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private TaskService taskService;

    /**
     *  <p>
     *      当流程执行到定时器边界事件依附的流程活动（如用户任务、子流程等）时，工作流引擎会创建一个定时器，当定时器触发后，流程会沿定时器边界事件的外出顺序流继续流转。
     *   如果该边界事件设置为中断事件，依附的流程活动将被终止。
     *  </p>
     *  <p>
     *      定时器边界事件表示为依附在流程活动边界上、带有定时器图标的圆环。如图所示，两个用户任务边界上分别依附着一个定时器边界事件，其中，左侧定时器边界事件的圆环是实线，
     *   代表它是边界中断事件；右侧定时器边界事件的圆环是虚线，代表它是边界非中断事件。<br/><br/>
     *   <img src="https://free4.yunpng.top/2025/05/08/681c6565caf27.png" />
     *  </p><br/>
     *  <p>
     *      具体事件定义格式如下所示：
     *      <pre>
     *          {@code
     *              <process id="timerBoundaryEventProcess">
     *                  <!-- 定义用户任务节点 -->
     *                  <userTask id="theUserTask" name="审批"/>
     *                  <!-- 定义边界事件 -->
     *                  <boundaryEvent id="timerBoundaryEvent" name="Timer" attachedToRef="theUserTask" cancelActivity="false">
     *                      <!-- 包含 timerEventDefinition子元素，代表定时器边界事件 -->
     *                      <timerEventDefinition>
     *                          <timeDuration>PT1M</timeDuration>
     *                      </timerEventDefinition>
     *                 </boundaryEvent>
     *              </process>
     *          }
     *      </pre>
     *  </p>
     *  <br/>
     *  <h2>案例演示</h2>
     *  <hr/>
     *  <p>
     *      该流程为客户投诉处理流程：客户提交投诉信息后，先由一线客服人员处理。如果不超过2小时一线客服处理完成，则流程将流转到“结案”节点；如果超过2小时一线客服仍然未
     *  能处理完成，则自动流转给二线客服人员继续处理。这个示例是通过在“一线客服处理”用户任务上附加定时器边界事件来实现这一需求的。
     *  </p><br/>
     *  <p>
     *      <b>流程定义文件：</b>{@code flow/boundTimerEvent.bpmn20.xml}<br/>
     *      <b>流程预览图：</b><br/>
     *      <img src="https://free4.yunpng.top/2025/05/08/681c689c29483.png" />
     *  </p>
     **/
    @Test
    public void test() {
        Deployment deploy = repositoryService.createDeployment()
                .name("定时器边界事件案例")
                .addClasspathResource("flow/boundTimerEvent.bpmn20.xml")
                .deploy();
        log.info("部署流程定义：{}", deploy.getId());
        //启动流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("boundTimerEvent");
        log.info("启动流程实例：{}", processInstance.getId());
        TaskQuery taskQuery = taskService.createTaskQuery()
                .processInstanceId(processInstance.getId());
        //查询子流程第一个任务
        Task firstTaskOfSubProcess = taskQuery.singleResult();
        log.info("发起流程后，当前流程所在用户任务为：{}", firstTaskOfSubProcess.getName());
        log.info("当前任务执行人：{}",firstTaskOfSubProcess.getAssignee());
        //客户投诉内容填写提交
        taskService.complete(firstTaskOfSubProcess.getId());
        //查询此时任务流转所在节点
        Task curTask = taskQuery.singleResult();
        log.info("当前任务：{}", curTask.getName());
        log.info("当前任务执行人：{}",curTask.getAssignee());
        try {
            //休眠2分钟
            Thread.sleep(2*60 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //超时后，查询此时流程所在任务节点
        Task task = taskQuery.singleResult();
        log.info("当前任务：{}", task.getName());
        log.info("当前任务执行人：{}",task.getAssignee());

        /**
         *  演示结果：
         * 2025-05-08 16:27:56.112  INFO 40940 --- [           main] c.b.n.f.e.bound.timer.BoundTimerEvent    : 部署流程定义：577a4b27-2be6-11f0-86ae-50ebf6ec8f6d
         * 2025-05-08 16:27:56.136  INFO 40940 --- [           main] c.b.n.f.e.bound.timer.BoundTimerEvent    : 启动流程实例：57a1a94b-2be6-11f0-86ae-50ebf6ec8f6d
         * 2025-05-08 16:27:56.147  INFO 40940 --- [           main] c.b.n.f.e.bound.timer.BoundTimerEvent    : 发起流程后，当前流程所在用户任务为：客户投诉
         * 2025-05-08 16:27:56.147  INFO 40940 --- [           main] c.b.n.f.e.bound.timer.BoundTimerEvent    : 当前任务执行人：user1
         * 2025-05-08 16:27:56.190  INFO 40940 --- [           main] c.b.n.f.e.bound.timer.BoundTimerEvent    : 当前任务：一线客服处理
         * 2025-05-08 16:27:56.190  INFO 40940 --- [           main] c.b.n.f.e.bound.timer.BoundTimerEvent    : 当前任务执行人：妲己
         * 2025-05-08 16:29:56.201  INFO 40940 --- [           main] c.b.n.f.e.bound.timer.BoundTimerEvent    : 当前任务：二线客服处理
         * 2025-05-08 16:29:56.201  INFO 40940 --- [           main] c.b.n.f.e.bound.timer.BoundTimerEvent    : 当前任务执行人：貂蝉
         **/
    }
}
